/*
 * @Author: 9ilk 3535851673@qq.com
 * @Date: 2025-03-19 19:47:14
 * @LastEditors: 9ilk 3535851673@qq.com
 * @LastEditTime: 2025-03-19 23:03:20
 * @FilePath: /zhuang/ETEpollServer/IOService.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <iostream>
#include <memory>
#include <functional>
#include "Reactor.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "Connection.hpp"
#include"Epoller.hpp"
using namespace std;
using func_t = function<string(string &)>; // 业务回调函数

class IOService : public Connection
{
public:
    IOService(int sockfd)
    {
        // SetNonBlock(sockfd);//设置文件描述符非阻塞
        SetSockfd(sockfd);
        SetEvents(EPOLLIN | EPOLLOUT);
    }
    virtual void Sender() override
    {
        // 直接写
        while (true)
        {
            ssize_t s = ::send(Sockfd(), OutString().c_str(), OutString().size(), 0);
            if (s > 0)
            {
                // 成功 移除outbuffer已经发送的
                DiscardOutString(s);
            }
            else if (s == 0)
            {
                break;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                { // 缓冲区满了 下次再来
                    break;
                }
                else if (errno == EINTR) // 中断 关闭连接
                {
                    continue;
                }
                else
                {
                    Excepter();
                    return;
                }
            }
        }
        // 走到这里 要么1.outbuffer emoty 2. 发送缓冲区写满了 && outbuffer不为空->此时需要使能写 关心写事件
        if (!isOutbufferEmpty())
            GetOwner()->EnabelReadWrite(Sockfd(), true, true);
        else
            GetOwner()->EnabelReadWrite(Sockfd(), true, false); // outbuffer为空发完 关闭写事件
    }

    virtual void Recver() override
    {
        LOG(LogLevel::DEBUG) << "into IO Recv..\n";
        // 1.循环读取所有数据
        while (true)
        {
            char buffer[4096];
            ssize_t s = ::recv(Sockfd(), buffer, sizeof(buffer) - 1, 0); // 非阻塞
            if (s > 0)
            {
                // 读取成功存到缓冲区
                buffer[s] = 0;
                Append(buffer);
            }
            if (s == 0) // 对端关闭连接
            {
                Excepter();
                return;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break; // 本轮数据读完
                }
                else if (errno == EINTR) // 读取过程被中断
                {
                    continue;
                }
                else
                {
                    // 真正发生错误
                    Excepter();
                    return;
                }
            }
        }
        // 走到这 本轮数据一定读取完了
        cout << "outbuffer: \n"
             << Inbuffer() << endl;
        // 你能确保你读到的消息，就是一个完整的报文吗？？不能！！！
        // 我们怎么知道，读到了完整的请求呢？？协议！！！
        string reasult;
        if (_on_message)
            reasult = _on_message(Inbuffer());
        // 添加应答信息
        AppendToOut(reasult);
        // 写的话不为空直接写 如果写失败(即满了)才托管给epoll
        if (!isOutbufferEmpty())
        {
            LOG(LogLevel::DEBUG) << "No empty...\n";
            //Sender();
            GetOwner()->EnabelReadWrite(Sockfd(),true,true);//也可使能写!!!
        }
    }
    void RegisterMessage(func_t on_message)
    {
        _on_message = on_message;
    }

    virtual void Excepter() override
    {
        // IO读取时所有的异常处理 全部都会转化为这个函数调用
        // 出现异常 我们应该打印日志 差错处理(从epoll移除节点 关闭文件 移除连接的管理)
        LOG(LogLevel::INFO) << "客户端连接可能结束，进行异常处理...\n";
        GetOwner()->DelConnection(Sockfd());
    }

private:
    func_t _on_message;
};